//引入ws模块用于创建服务器 
const WebSocket = require("ws");
//引入数据库信息
const cofdb = require('./Model/db');
//引入数据库语句
const sqlChat = require('./Model/chat/mysql');
//引入定义方法模块
const exeChat = require('./Model/chat/query');
//引入mysql数据库模块
const mysql = require('mysql');
//引入MD5模块
const md5 = require('blueimp-md5');

//建立通讯通道
const ws = new WebSocket.Server({ port: 9437, host: '127.0.0.1' });
console.log("通讯服务启动成功!");


//连接数据库
connlink();
function connlink() {
    //连接数据库
    conn = mysql.createConnection(cofdb.mysql_cof);
    conn.connect((err) => {
        if (err) {
            throw err;
            setTimeout('connlink()', 1000);
        }
    });
    //断开重连
    conn.on('error', (err) => {
        console.log("数据库断开重连...");
        console.log(err);
        if (err.code === 'PROTOCOL_CONNECTION_LOST') {
            connlink();
            console.log("数据库已重连...");

        }
    });
}



//
let clients = {};
//唯一标识
let clientName = 0;
let ws_msg_init;
const sqlnews = sqlChat.user.news;//消息语句
const sqlkey = sqlChat.user.key;//密钥语句
const sqlkefu = sqlChat.user.kefu;//客服语句
let modOne, modTwo, modThree, modFour, modCoun;

//服务初始化在线列表
exeChat.modChatData(conn, sqlnews[6], 0);

//通讯触发
ws.on("connection", (client) => {
    // client.name = ++clientName
    clients[client.name] = client;
    //得到消息时
    client.on("message", (msg) => {
        //json解析消息源码
        var msg_data = JSON.parse(msg);

        //用户唯一标识
        client.name = msg_data.uid;

        //消息发送对象标识
        client.visit = msg_data.visit;
        clients[client.name] = client;


        console.log("收到：" + msg_data) //客户端接受到的信息

        //获取初始化标记
        ws_msg_init = msg_data.init;
        //获取消息加载标记
        ws_msg_news = msg_data.type;

        //判断是否为客服点击用户列表
        if (ws_msg_news === 'record') {
            if (msg_data.cid != undefined && msg_data.visit != undefined) {
                var sign = md5(msg_data.cid + msg_data.visit);
                //获取历史消息
                exeChat.getChatData(conn, sqlnews[0], [sign]).then((res => {
                    if (res) {
                        console.log(res);

                        if (res.length > 0) {
                            //追加数据
                            let _dat = {};//创建储存数组
                            _dat.data = res.concat(msg_data);//数组追加合并到data中
                            _dat.info = {};//定义子数组
                            //发送提示消息
                            msgSend(client, JSON.stringify(_dat), msg_data.visit);
                        }
                    }
                }));
                //数据处理
                var _isnews = ['0', msg_data.cid];
                console.log("修改" + _isnews);
                //用户未读消息数
                exeChat.modChatData(conn, sqlnews[7], _isnews);
            }
            console.log("点你");


        } else {
            //判断初始化连接事件是否执行
            if (msg_data.init && msg_data.init.length > 0) {
                console.log(msg_data.uid + "进入~~~");
                //判断初始化类型
                if (ws_msg_init == 'kefu') {//客服身份
                    console.log("客服初始化连接");
                    //判断消息类型是不是列表
                    if (msg_data.type == 'list') {
                        console.log("客服初始化在线列表");
                        //获取用户列表
                        exeChat.getChatData(conn, sqlnews[5], [msg_data.cid]).then((res => {
                            //密钥查询返回是否为真
                            if (res) {
                                // console.log(res);
                                //为全局变量赋值用户列表数据
                                modOne = res;
                                let stay = [];//定义空在线变量
                                let nostay = [];//定义空不在线变量
                                for (const key in modOne) {
                                    //区分在线与不在线
                                    if (modOne[key]['v4_state'] == 0) {
                                        //不在线人数统计
                                        nostay.push({ "title": modOne[key]['v4_user'], "mumber": modOne[key]['v4_unread'] });
                                    } else {
                                        //在线人数统计
                                        stay.push({ "title": modOne[key]['v4_user'], "mumber": modOne[key]['v4_unread'] });
                                    }
                                }
                                //发送提示消息
                                msgSend(client, msgList(stay, nostay), client.name);
                            } else {
                                console.log('用户列表获取出失败！');
                            }
                        })).catch((reason => {
                            console.log('用户列表获取出错：' + reason);
                        }))
                    } else {//一般消息
                        //数据处理
                        var _isnews = ['1', client.name];
                        //用户账号改为在线
                        exeChat.modChatData(conn, sqlnews[8], _isnews);
                        console.log("客服初始化提示消息");
                        //发送提示消息
                        msgSend(client, JSON.stringify(msg_data), client.name);
                    }
                } else {//visitor 用户身份
                    console.log("用户初始化连接");
                    //验证密钥有效性
                    exeChat.getChatData(conn, sqlkey[0], [msg_data.key]).then((res => {
                        //密钥查询返回是否为真
                        if (res) {
                            console.log("密钥有效");
                            //为全局变量赋值密钥数据
                            modOne = res;
                            console.log(modOne);
                            //获取客服标识
                            return exeChat.getChatData(conn, sqlkefu[0], [res[0]['v3_form']]);
                        } else {
                            console.log('密钥无效');
                        }
                    })).catch((reason => {
                        console.log('验证错误：' + reason);
                    })).then((res => {
                        if (res) {
                            modTwo = res;
                            // console.log("列表", res);
                            //产生一个随机数
                            modCoun = Math.floor(Math.random() * modTwo.length);
                            //判断数据长度
                            if (res.length > 0) {
                                var sign = md5(client.name + res[modCoun]['v_name']);
                                //获取历史消息
                                return exeChat.getChatData(conn, sqlnews[0], [sign]);
                            } else {
                                //查询当前机构客服数量为0
                                msgSend(client, JSON.stringify(msgErr("当前公司未设置客服人员", "support")), client.name);
                            }
                        }
                    })).then((res => {
                        if (res) {
                            //为全局变量赋值客服数据
                            modThree = res;
                            console.log("客服数据获取成功");
                            //验证数据存在
                            if (msg_data.uid) {
                                modFour = msg_data.uid;
                                //判断历史消息
                                if (res.length > 0) {
                                    //返回客服标识
                                    msg_data.visit = modTwo[modCoun]['v_name'];
                                    //追加数据
                                    let _dat = {};//创建储存数组
                                    _dat.data = res.concat(msg_data);//数组追加合并到data中
                                    _dat.info = {};//定义子数组
                                    _dat.info.key = msg_data.key;//添加密钥到子数组
                                    _dat.info.visit = msg_data.visit;//添加客服标识到子数组
                                    msg_data = _dat;
                                }
                                console.log(modFour);

                                //查询用户是否存在过
                                return exeChat.getChatData(conn, sqlnews[3], [modFour]);
                            }
                        }
                    })).then((res => {
                        if (res) {
                            console.log("用户", res);
                            if (res.length > 0) {
                                console.log("用户" + msg_data.uid, "客服" + res[0]['v4_kefu']);
                                //数据处理
                                var _isnews = ['1', modFour];
                                console.log("修改" + _isnews);
                                //用户账号改为在线
                                exeChat.modChatData(conn, sqlnews[4], _isnews);
                                //设置返回客服标识
                                msg_data.visit = res[0]['v4_kefu'];
                            } else {
                                console.log("用户" + msg_data.uid, "客服" + modTwo[modCoun]['v_name']);
                                //数据处理
                                var _isnews = [msg_data.uid, modTwo[modCoun]['v_name'], 1];
                                console.log("插入" + _isnews);
                                //用户账号新增记录
                                exeChat.addChatData(conn, sqlnews[2], _isnews);
                                console.log('长度' + modTwo.length, "生成" + modCoun);
                                //设置返回客服标识
                                msg_data.visit = modTwo[modCoun]['v_name'];
                            }

                            //发送提示消息
                            msgSend(client, JSON.stringify(msg_data), client.name);
                            //客服在线验证
                            msgSend(client, JSON.stringify(''), msg_data.visit);
                            return exeChat.getChatData(conn, sqlnews[5], [msg_data.visit]);
                        }
                    })).then((res => {
                        //密钥查询返回是否为真
                        if (res) {
                            var stay_data = res;
                            let stay = [];//定义空在线变量
                            let nostay = [];//定义空不在线变量
                            for (const key in stay_data) {
                                //区分在线与不在线
                                if (stay_data[key]['v4_state'] == 0) {
                                    //不在线人数统计
                                    nostay.push({ "title": stay_data[key]['v4_user'], "mumber": stay_data[key]['v4_unread'] });
                                } else {
                                    //在线人数统计
                                    stay.push({ "title": stay_data[key]['v4_user'], "mumber": stay_data[key]['v4_unread'] });
                                }
                            }
                            //判断客服是否在线
                            if (clients['list' + msg_data.visit] != undefined) {
                                //更新客服用户列表
                                msgSend(client, msgList(stay, nostay), 'list' + msg_data.visit);
                            }
                        } else {
                            console.log('用户列表获取出失败！');
                        }
                    }));
                    // msgSend(client, JSON.stringify(msg_data), msg_data.visit);
                }
            } else {
                //判断是否是客服消息
                if (msg_data.user == 'support') {
                    //获取客服数据
                    exeChat.getChatData(conn, sqlkefu[1], [msg_data.uid]).then((res => {
                        //数据获取成功
                        if (res) {
                            console.log(res);
                            //消息记录唯一标识
                            var issign = md5(msg_data.visit + msg_data.uid);
                            //判断消息类型
                            if (msg_data.type == 'pic') {
                                //图片消息数据处理
                                isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v_form'], msg_data.user, issign]
                            } else {
                                //文本消息数据处理
                                isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v_form'], msg_data.user, issign]
                            }
                            //发送消息
                            msgSend(client, JSON.stringify(msg_data), msg_data.visit, isnews);
                        }
                    })).catch((reason => {
                        console.log('错误：' + reason);
                    }));
                } else {
                    //验证密钥有效性
                    exeChat.getChatData(conn, sqlkey[0], [msg_data.key]).then((res => {
                        //密钥查询返回是否为真
                        if (res) {
                            console.log("密钥有效");
                            //为全局变量赋值密钥数据
                            modOne = res;
                            console.log(modOne);
                            //获取客服标识
                            return exeChat.getChatData(conn, sqlkefu[0], [res[0]['v3_form']]);
                        } else {
                            console.log('密钥失效');
                        }
                    })).catch((reason => {
                        console.log('验证错误：' + reason);
                    })).then((res => {
                        if (res) {
                            //为全局变量赋值客服数据
                            modTwo = res;
                            if (res.length > 0) {
                                console.log("客服数据获取成功" + modTwo[0]['v_form']);
                                console.log(res);
                                //消息记录唯一标识
                                var issign = md5(msg_data.uid + msg_data.visit);
                                //判断消息类型
                                if (msg_data.type == 'pic') {
                                    //图片消息数据处理
                                    isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, modTwo[0]['v_form'], msg_data.user, issign]
                                } else {
                                    //文本消息数据处理
                                    isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, modTwo[0]['v_form'], msg_data.user, issign]
                                }
                                //发送消息
                                msgSend(client, JSON.stringify(msg_data), res[0]['v_name'], isnews);
                            } else {
                                //发送消息
                                msgSend(client, JSON.stringify(msg_data), client.name);
                            }
                            //更新未读消息
                            msgUnread(msg_data.uid);
                        }
                    }));
                }
            }
        }
    });

    //连接关闭时
    client.on("close", () => {
        delete clients[client.name]
        console.log(client.name + "离开了~~~")
        //数据处理
        var _isnews = ['0', client.name];
        //用户账号改为离线
        exeChat.modChatData(conn, sqlnews[4], _isnews);
        //获取用户接待客服标识
        exeChat.getChatData(conn, sqlnews[3], [client.name]).then((res => {
            if (res) {
                if (res.length > 0) {
                    //获取客服接待列表
                    exeChat.getChatData(conn, sqlnews[5], [res[0]['v4_kefu']]).then((res => {
                        //密钥查询返回是否为真
                        if (res) {
                            var stay_data = res;
                            let stay = '';//定义空在线变量
                            let nostay = '';//定义空不在线变量
                            for (const key in stay_data) {
                                //区分在线与不在线
                                if (stay_data[key]['v4_state'] == 0) {
                                    //不在线人数统计
                                    nostay = stay_data[key]['v4_user'] + "," + nostay;
                                } else {
                                    //在线人数统计
                                    stay = stay_data[key]['v4_user'] + "," + stay;
                                }
                            }
                            //在线用户数据
                            stay = stay.split(",");
                            //离线用户数据
                            nostay = nostay.split(",");
                            //判断客服是否在线
                            if (clients['list' + res[0]['v4_kefu']] != undefined) {
                                //更新客服用户列表
                                msgSend(client, msgList(stay, nostay), 'list' + res[0]['v4_kefu']);
                            } else {
                                //数据处理
                                var _isnews = ['0', res[0]['v4_kefu']];
                                //客服账号改为离线
                                exeChat.modChatData(conn, sqlnews[8], _isnews);
                            }
                        } else {
                            console.log('用户列表获取出失败！');
                        }
                    }));;
                }
            }
        }));
    });
})


//消息原型
function msgErr(_msg, _user = "visitor") {
    var data = JSON.stringify({
        "user": _user,//消息来源
        "time": '',
        "type": "text",//消息类型
        "msg": "<p>" + _msg + "</p>",//消息内容
    });
    return data;
}

//列表
function msgList(_stay, _nostay) {
    var data = JSON.stringify({
        "type": "list",//消息类型
        "data": {
            stay: _stay,//在线列表
            nostay: _nostay//不在线列表
        },//列表内容
    });
    return data;
}

//页面数据推送
function newscast(client, msg, _visit = '') {
    if (_visit == '') {
        _visit = client.name;
    } else {
        var va = _visit;
    }
    // var va = "list" + _visit;
    var msg_data = JSON.parse(msg);
    let data = '';
    var dat;
    var i = 0;
    for (var key in clients) {
        console.log(msg_data.key);
        console.log("数据测试");
        console.log("比测试2");
        data = key + "," + data;
        console.log(i + '用户标识:' + key);
    }
    dat = data.split(",");
    console.log("的" + msgList(dat));
    console.log('列表发送' + va);

    clients[va].send(msgList(dat));
    console.log(data);
}

function msgUnread(cid) {
    exeChat.getChatData(conn, sqlnews[3], [cid]).then((res => {
        if (res) {
            var _num = res[0]['v4_unread'] + 1;
            //数据处理
            var _isnews = [_num, cid];
            console.log("修改" + _isnews);
            //用户未读消息数
            exeChat.modChatData(conn, sqlnews[7], _isnews);
        }
    }))
}

//向指定客户端发送消息
function msgSend(client, msg, _obj, data = []) {
    //源消息转JSON
    var msg_data = JSON.parse(msg);

    //如果指定对象存在
    if (clients[_obj] != undefined) {
        //判断消息是否为空
        if (msg.length > 2) {
            if (data.length > 0) {
                //消息数据录入
                exeChat.addChatData(conn, sqlnews[1], data);
                //更新自身
                clients[client.name].send(msg);
            }
            //向指定对象发送消息
            clients[_obj].send(msg);
        } else {
            //离线消息
            var data = msgErr("您好，请问有什么能够帮助您的？", "support");
            //如果在线返回问候消息
            clients[client.name].send(data);
        }
    } else {
        //离线消息
        var data = msgErr("当前客服处于离线状态", "support");
        //如果对象不存在返回提示消息
        clients[client.name].send(data);
    }

    for (var key in clients) {
        console.log(key);
    }
}


//向客户端发送消息
function Broadcast(client, msg, _type) {
    //源消息转JSON
    var msg_data = JSON.parse(msg);

    if (_type == 'kefu') {

    } else {

    }
    // // modTwo;
    // //判断发送人是否为空
    // if (client.visit != '') {
    //     clients[client.name].send(msg)
    //     //如果指定用户在线
    //     if (clients[client.visit] != undefined) {
    //         var issign = md5(msg_data.uid + msg_data.visit);//消息记录唯一标识
    //         if (msg_data.type == 'pic') {
    //             //图片消息数据处理
    //             isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v3_form'], msg_data.user, issign]
    //         } else {
    //             //文本消息数据处理
    //             isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v3_form'], msg_data.user, issign]
    //         }
    //         //消息数据录入
    //         exeChat.addChatData(conn, sqlnews[1], isnews);
    //         //发送到指定用户
    //         clients[client.visit].send(msg);
    //     } else {
    //         //离线消息
    //         data = msgErr("当前客服处于离线状态", "support");
    //         clients[client.name].send(data);
    //     }
    // } else {
    //     console.log("客服" + res[0]['v3_key']);
    //     //获取客服标识
    //     return exeChat.getChatData(conn, sqlkefu, [res[0]['v3_form']]);
    // }




    /*
    //判断密钥是否存在
    if (msg_data.key && msg_data.key != undefined) {
        console.log("游客消息");
        const sqlkey = sqlChat.user.key[0];//密钥校捡语句
        const sqlkefu = sqlChat.user.kefu[0];//客服查询语句
        const sqlnews = sqlChat.user.news;//历史消息查询语句
        //验证密钥
        exeChat.getChatData(conn, sqlkey, [msg_data.key]).then((res => {
            //密钥查询返回
            if (res) {
                modOne = res;
                //二次验证密钥
                if (msg_data.key == res[0]['v3_key']) {
                    //判断发送人是否为空
                    if (client.visit != '') {
                        clients[client.name].send(msg)
                        //如果指定用户在线
                        if (clients[client.visit] != undefined) {
                            var issign = md5(msg_data.uid + msg_data.visit);//消息记录唯一标识
                            if (msg_data.type == 'pic') {
                                //图片消息数据处理
                                isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v3_form'], msg_data.user, issign]
                            } else {
                                //文本消息数据处理
                                isnews = [msg_data.uid, msg_data.visit, msg_data.msg, msg_data.type, msg_data.time, res[0]['v3_form'], msg_data.user, issign]
                            }
                            //消息数据录入
                            exeChat.addChatData(conn, sqlnews[1], isnews);
                            //发送到指定用户
                            clients[client.visit].send(msg);
                        } else {
                            //离线消息
                            data = msgErr("当前客服处于离线状态", "support");
                            clients[client.name].send(data);
                        }
                    } else {
                        console.log("客服" + res[0]['v3_key']);
                        //获取客服标识
                        return exeChat.getChatData(conn, sqlkefu, [res[0]['v3_form']]);
                    }
                }
            } else {
                console.log('密钥错误：');
            }
        })).catch((reason => {
            console.log('验证未知错误');
        })).then((res => {
            if (res) {
                modTwo = res;
                //判断数据长度
                if (res.length > 0) {
                    var sign = md5(client.name + res[0]['v_name']);
                    console.log("用户标识" + sign);
                    //获取历史消息
                    return exeChat.getChatData(conn, sqlnews[0], [sign]);
                } else {
                    clients[client.name].send(msgErr("当前公司未设置客服人员", "support"));
                }
            }
        })).then((res => {
            if (res) {
                console.log(res);
                console.log("消息");
                //判断历史消息
                if (res.length > 0) {
                    console.log("空");
                    //返回客服标识
                    msg_data.visit = modTwo[0]['v_name'] + "呵呵";
                    //追加数据
                    let _dat = {};//创建储存数组
                    _dat.data = res.concat(msg_data);//数组追加合并到data中
                    _dat.info = {};//定义子数组
                    _dat.info.key = msg_data.key;//添加密钥到子数组
                    _dat.info.visit = msg_data.visit;//添加客服标识到子数组
                    // console.log(_dat);
                    clients[client.name].send(JSON.stringify(_dat));
                } else {
                    //返回客服标识
                    msg_data.visit = modTwo[0]['v_name'];
                    clients[client.name].send(JSON.stringify(msg_data));
                    newscast(client, JSON.stringify(msg_data), 'list' + msg_data.visit);
                }
            }
        }));
    } else {
        console.log("无效客服消息");
        //判断发送人是否为空
        if (client.visit != '') {
            clients[client.name].send(msg)
            //如果指定用户不在线
            if (clients[client.visit] != undefined) {
                //指定到用户
                clients[client.visit].send(msg);
            } else {
                //离线消息
                data = msgErr("处于离线状态");
                clients[client.name].send(data);
            }
        } else {
            clients[client.name].send(msg);
        }
 
    }
*/
    // for (var key in clients) {
    //     console.log(key);
    // }

    // 向所有人发送
    // for (var key in clients) {
    //client.name + "说：" +
    // console.log(clients.length);
    // clients[key].send(msg)
    // }
}
